package com.melody.android.logic

import android.content.Context
import android.graphics.Color
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.ForegroundColorSpan
import com.melody.android.logic.util.MediaPlayer
import java.io.BufferedReader
import java.io.InputStreamReader

class LyricsManager {

    private var currentLineIndex = 0
    private val lyricsLines: MutableList<LyricsLine> = ArrayList()
    private val lyricsHandler: Handler = Handler(Looper.getMainLooper(), LyricsHandlerCallback())
    private var lyricsDisplayListener: LyricsDisplayListener? = null

    /**
     * 设置LyricsDisplayListener监听对象
     */
    fun setLyricsDisplayListener(listener: LyricsDisplayListener) {
        this.lyricsDisplayListener = listener
    }

    /**
     * 从文件中加载歌词文本
     * @param context 上下文对象
     * @param fileName 文件名
     * @return 歌词文本
     */
    fun loadLyricsFromFile(context: Context, fileName: String): String {
        val assetManager = context.assets
        val stringBuilder = StringBuilder()

        try {
            val inputStream = assetManager.open(fileName)
            val bufferReader = BufferedReader(InputStreamReader(inputStream))
            var line: String? = bufferReader.readLine()
            while (line != null) {
                stringBuilder.append(line).append('\n')
                line = bufferReader.readLine()
            }
            bufferReader.close()
        } catch (e: Exception) {
            e.printStackTrace()
        }

        return stringBuilder.toString()
    }

    /**
     * 将歌词文本解析成歌词行对象, 并添加到歌词行列表中
     * @param lyricsText 歌词文本
     */
    fun parseLyrics(lyricsText: String) {
        // TODO: 逻辑修改 多次频繁退出/进入SongActivity时会使得歌词显示逻辑混乱
        lyricsLines.clear()

        val lines = lyricsText.split("\\r?\\n".toRegex()).toTypedArray()
        for (line in lines) {
            val lyricsLine = parseLyricsLine(line)
            if (lyricsLine != null) {
                lyricsLines.add(lyricsLine)
            }
        }
    }

    /**
     * 开始更新歌词显示
     */
    fun startUpdatingLyrics() {
        lyricsHandler.sendEmptyMessage(MSG_UPDATE_LYRICS)
    }

    /**
     * 停止更新歌词显示
     */
    fun stopUpdatingLyrics() {
        lyricsHandler.removeMessages(MSG_UPDATE_LYRICS)
    }

    /**
     * 解析一行歌词文本
     * @param lineText 一行歌词文本
     * @return 歌词行对象, 解析失败则返回null
     */
    private fun parseLyricsLine(lineText: String): LyricsLine? {
        val startIndex = lineText.indexOf("[")
        val endIndex = lineText.indexOf("]")

        if (startIndex in 0 until endIndex) {
            val timeTag = lineText.substring(startIndex + 1, endIndex)
            val lyricsText = lineText.substring(endIndex + 1).trim { it <= ' ' }
            val timeMillis = parseTimeTag(timeTag)

            return LyricsLine(timeMillis, lyricsText)
        }
        return null
    }

    /**
     * 解析时间标签
     * @param timeTag 时间标签 格式为 分钟:秒数
     * @return 时间戳(以毫秒为单位)
     */
    private fun parseTimeTag(timeTag: String): Long {
        val parts = timeTag.split(":".toRegex()).toTypedArray()
        if (parts.size >= 2) {
            val minutes = parts[0].toInt()
            val seconds = parts[1].toFloat()

            return (minutes * 60 + seconds).toLong() * 1000
        }
        return 0
    }

    /**
     * 根据当前时间更新当前歌词行的索引
     * @param currentTime 当前播放时间(以毫秒为单位)
     */
    private fun updateCurrentLineIndex(currentTime: Long) {
        for (i in lyricsLines.size - 1 downTo 0) {
            if (lyricsLines[i].timeMillis <= currentTime) {
                currentLineIndex = i
                break
            }
        }
    }

    /**
     * 更新歌词的显示
     */
    private fun updateLyricsDisplay() {
        val builder = SpannableStringBuilder()
        for (i in lyricsLines.indices) {
            val lineText = lyricsLines[i].lyricsText
            if (i == currentLineIndex) {
                val spannedText = formatLyricsText(lineText)
                builder.append(spannedText)
            } else {
                builder.append(lineText)
            }
            builder.append("\n")
        }

        lyricsDisplayListener?.onSelectedLyricsUpdate(builder)
        lyricsDisplayListener?.onScrollToLine(currentLineIndex)
    }

    /**
     * 格式化歌词文本
     * @param text 格式化后的歌词文本
     */
    private fun formatLyricsText(text: String): Spanned {
        val span = ForegroundColorSpan(Color.RED)
        val builder = SpannableStringBuilder(text)
        builder.setSpan(span, 0, text.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        return builder
    }

    /**
     * 获取当前歌曲的播放时间
     */
    private fun getCurrentPlaybackTime(): Long {
        return MediaPlayer.getSongCurrentPosition().toLong()
    }

    private inner class LyricsHandlerCallback : Handler.Callback {
        override fun handleMessage(msg: Message): Boolean {
            if (msg.what == MSG_UPDATE_LYRICS) {
                val currentTime = getCurrentPlaybackTime()  // 获取当前歌曲的播放时间
                updateCurrentLineIndex(currentTime)         // 根据当前歌曲的播放时间更新当前歌词行的索引
                updateLyricsDisplay()                       // 更新歌词的显示
                lyricsHandler.sendEmptyMessageDelayed(MSG_UPDATE_LYRICS, UPDATE_INTERVAL)   // 间隔一段时间后再次发送更新歌词的消息

                return true // 表示消息已处理
            }
            return false    // 表示消息未处理
        }
    }

    /**
     * LyricsManager伴生对象 单例模式
     */
    companion object {
        private var instance: LyricsManager? = null
        private const val MSG_UPDATE_LYRICS = 1
        private const val UPDATE_INTERVAL: Long = 100   // 歌词更新的时间间隔

        fun getInstance(): LyricsManager {
            if (instance == null) {
                instance = LyricsManager()
            }
            return instance!!
        }
    }

    /**
     * 歌词行对象
     * @param timeMillis 歌词对应的时间戳(以毫秒为单位)
     * @param lyricsText 歌词文本内容
     */
    private inner class LyricsLine(val timeMillis: Long, val lyricsText: String)

    /**
     * 歌词显示回调接口
     */
    interface LyricsDisplayListener {
        /**
         * 更新选中的歌词文本
         * @param lyricsText 待选中的歌词文本
         */
        fun onSelectedLyricsUpdate(lyricsText: CharSequence)

        /**
         * 滚动歌词文本使其显示在合适的位置
         * @param currentLineIndex 当前歌词行的索引
         */
        fun onScrollToLine(currentLineIndex: Int)
    }

}